using System;
using Microsoft.Win32;

namespace SharpObjects.Utils
{
    public class WindowsRegistry
    {
        public readonly static WindowsRegistryKey CurrentUser = new WindowsRegistryKey(WindowsRegistryKey.eWindowsRegistryKey.HKEY_CURRENT_USER);
        public readonly static WindowsRegistryKey LocalMachine = new WindowsRegistryKey(WindowsRegistryKey.eWindowsRegistryKey.HKEY_LOCAL_MACHINE);
        public readonly static WindowsRegistryKey ClassesRoot = new WindowsRegistryKey(WindowsRegistryKey.eWindowsRegistryKey.HKEY_CLASSES_ROOT);
        public readonly static WindowsRegistryKey CurrentConfig = new WindowsRegistryKey(WindowsRegistryKey.eWindowsRegistryKey.HKEY_CURRENT_CONFIG);
        public readonly static WindowsRegistryKey Users = new WindowsRegistryKey(WindowsRegistryKey.eWindowsRegistryKey.HKEY_USERS);


        public class WindowsRegistryKey
        {
            public enum eWindowsRegistryKey
            {
                HKEY_CURRENT_USER,
                HKEY_LOCAL_MACHINE,
                HKEY_CLASSES_ROOT,
                HKEY_CURRENT_CONFIG,
                HKEY_USERS
            }

            protected string keyName;
            protected WindowsRegistryValue<string> stringValue;
            protected WindowsRegistryValue<bool> boolValue;
            protected WindowsRegistryValue<int> intValue;
            protected WindowsRegistryValue<long> longValue;
            protected WindowsRegistryValue<string[]> multiStringValue;

            public WindowsRegistryKey(eWindowsRegistryKey key)
            {
                this.keyName = key.ToString();

                this.stringValue = new WindowsRegistryValue<string>(this.keyName);
                this.boolValue = new WindowsRegistryValue<bool>(this.keyName);
                this.intValue = new WindowsRegistryValue<int>(this.keyName);
                this.longValue = new WindowsRegistryValue<long>(this.keyName);
                this.multiStringValue = new WindowsRegistryValue<string[]>(this.keyName);
            }

            public WindowsRegistryValue<string> String { get { return this.stringValue; } }
            public WindowsRegistryValue<bool> Boolean { get { return this.boolValue; } }
            public WindowsRegistryValue<int> Integer { get { return this.intValue; } }
            public WindowsRegistryValue<long> Long { get { return this.longValue; } }
            public WindowsRegistryValue<string[]> MultiString { get { return this.multiStringValue; } }

        }

        public class WindowsRegistryValue<T>
        {
            protected string keyName;

            public WindowsRegistryValue(string keyName)
            {
                this.keyName = keyName;
            }

            public T GetValue(string subKey, string valueName)
            {
                object value = Registry.GetValue(this.keyName + "\\" + subKey, valueName, null);

                if (value == null)
                {
                    throw new ApplicationException("Registry value does not exist: " + this.keyName + "\\" + subKey + "\\" + valueName);
                }
                else
                {
                    return (T)value;
                }
            }

            public T GetValue(string subKey, string valueName, T defaultValue)
            {
                object value = Registry.GetValue(this.keyName + "\\" + subKey, valueName, null);

                if (value == null)
                {
                    return defaultValue;
                }
                else
                {
                    return (T)value;
                }
            }

            public void SetValue(string subKey, string valueName, T value)
            {
                Registry.SetValue(this.keyName + "\\" + subKey, valueName, value);
            }
        }
    }

}